package cn.iocoder.yudao.module.dify.util;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;

public class DifyFileUploadUtil {
    private static final int TIMEOUT = 30 * 1000; // 30秒超时

    /**
     * 通过Multipart格式上传远程文件
     * @param apiUrl        接口地址
     * @param apiKey        API密钥
     * @param remoteFileUrl 远程文件URL
     * @param userIdentifier 用户标识
     * @return 服务器响应内容
     * @throws IOException 当网络或文件操作失败时抛出
     */
    public static String uploadViaMultipart(String apiUrl, String apiKey,
                                            String remoteFileUrl, Long userIdentifier)
            throws IOException {

        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(TIMEOUT)
                .setSocketTimeout(TIMEOUT)
                .build();

        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(config)
                .build()) {

            // 1. 获取远程文件内容和元数据
            byte[] fileData = downloadFile(remoteFileUrl);
            String filename = getFileNameFromUrl(remoteFileUrl);

            // 2. 构建Multipart请求
            HttpPost httpPost = new HttpPost(apiUrl);
            httpPost.setHeader("Authorization", "Bearer " + apiKey);

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(StandardCharsets.UTF_8);

            // 添加用户标识字段
            builder.addTextBody("user", userIdentifier.toString(), ContentType.TEXT_PLAIN);

            // 添加文件字段（使用ByteArrayInputStream提高性能）
            builder.addBinaryBody(
                    "file",
                    new ByteArrayInputStream(fileData),
                    ContentType.APPLICATION_OCTET_STREAM,
                    filename
            );

            // 3. 设置请求实体
            httpPost.setEntity(builder.build());

            // 4. 执行请求并返回响应
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                return EntityUtils.toString(response.getEntity());
            }
        }
    }

    /**
     * 下载远程文件到字节数组
     */
    private static byte[] downloadFile(String fileUrl) throws IOException {
        URL url = new URL(fileUrl);
        URLConnection connection = url.openConnection();
        try (InputStream input = connection.getInputStream();
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096]; // 缓冲区大小为 4KB
            int bytesRead;
            while ((bytesRead = input.read(buffer)) != -1) { // 循环读取数据
                output.write(buffer, 0, bytesRead); // 将读取的数据写入 ByteArrayOutputStream
            }
            return output.toByteArray(); // 返回完整的字节数组
        }
    }

    /**
     * 从URL中提取文件名
     */
    private static String getFileNameFromUrl(String url) {
        String path = url.substring(url.lastIndexOf('/') + 1);
        int paramsIndex = path.indexOf('?');
        return (paramsIndex == -1) ? path : path.substring(0, paramsIndex);
    }


    /**
     * 校验返回格式是否正确
     */
    // 预编译正则表达式
    private static final Pattern JSON_PATTERN = Pattern.compile(
            "^\\{\\s*" +
                    "\"id\"\\s*:\\s*\"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\"\\s*," +
                    "\"name\"\\s*:\\s*\"[^\\/\"]+\\.[a-z]{3,4}\"\\s*," +  // 文件名.扩展名格式
                    "\"size\"\\s*:\\s*\\d+\\s*," +  // 正整数
                    "\"extension\"\\s*:\\s*\"[a-z]{2,5}\"\\s*," +  // 小写字母扩展名
                    "\"mime_type\"\\s*:\\s*\"[a-z]+\\/[a-z-+]+\"\\s*," +  // MIME类型格式
                    "\"created_by\"\\s*:\\s*\\d+\\s*," +  // 用户ID
                    "\"created_at\"\\s*:\\s*\\d+\\s*" +  // UNIX时间戳
                    "\\s*\\}$",
            Pattern.CASE_INSENSITIVE
    );

    public static boolean validate(String json) {
        return JSON_PATTERN.matcher(json).matches();
    }
}